package text;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.Map;

public class Server {
    private ServerSocket serverSocket;
    private Map<String, PrintWriter> allOut=new HashMap<>();

    public Server(){
        try {
            System.out.println("Server is running...");
            serverSocket=new ServerSocket(8080);
            System.out.println("Server is Securser...");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void start(){

        //获取socket
        //循环等待用户连接
        while (true){
            try {
                System.out.println("Client is connecting...");
                Socket socket=serverSocket.accept();
                System.out.println("Client is connected...");

                //
                clientHandler handler=new clientHandler(socket);
                Thread t=new Thread(handler);
                t.start();



            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public static void main(String[] args) {
        Server server=new Server();
        server.start();
    }
    class clientHandler implements Runnable{
        private String nikeName;
        private Socket socket;
        private String host;
        public clientHandler(Socket socket){
            this.socket=socket;
            host=socket.getInetAddress().getHostAddress();
        }
        public void run(){
            try {
                //获取输入流
                InputStream is= socket.getInputStream();
                InputStreamReader isr=new InputStreamReader(is, StandardCharsets.UTF_8);
                BufferedReader bf=new BufferedReader(isr);
                nikeName=bf.readLine();
                //获取输出流
                OutputStream os=socket.getOutputStream();
                OutputStreamWriter osw=new OutputStreamWriter(os, StandardCharsets.UTF_8);
                BufferedWriter bw=new BufferedWriter(osw);
                PrintWriter pw=new PrintWriter(bw,true);

                synchronized (allOut){
                    allOut.put(nikeName,pw);
                }

                // 调用群发方法 通知所有在线用户
                sendMessage(nikeName+"上线了,当前在线人数："+allOut.size());

                String message;
                while ((message=bf.readLine())!=null){
                    if (message.startsWith("@")){
                        // 私聊
                        sendMessageToothers(message);
                    }else {
                        // 群发消息
                        sendMessage(nikeName+"群发说:"+message);
                        // 保存到数据库 群聊信息toUser应该设置为null
                        saveMessage(nikeName,null,message);
                    }

                }
            } catch (IOException e) {
                // 断开连接 不处理
            } finally {
                synchronized (allOut) {
                    allOut.remove(nikeName);
                }
                // 下线广播
                sendMessage(nikeName+"下线了,当前在线人数："+allOut.size());
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // 广播
        private void sendMessage(String message){
            System.out.println(message);
            for (PrintWriter p:allOut.values()){
                p.println(message);
            }
        }
        // 私聊
        private void sendMessageToothers(String message){
            synchronized (allOut) {
                //判断格式是否正确:
                if (message.matches("@.+:.+")) {

                    String toName = message.substring(1, message.indexOf(":"));
                    String toMessage = message.substring(message.indexOf(":") + 1);
                    PrintWriter pw = allOut.get(toName);
                    if (pw != null) {
                        pw.println(nikeName + "悄悄地对你说：" + toMessage);
                        // 保存到数据库
                        saveMessage(nikeName,toName,toMessage);
                    } else {
                        PrintWriter pw1 = allOut.get(nikeName);
                        pw1.println("用户" + toName + "不在线");
                    }
                }else {
                    //给当前用户提升格式不正确
                    PrintWriter pw = allOut.get(nikeName);
                    pw.println("格式错误");
                }
            }
        }

        //将消息记录保存到数据库中建立连接
        private void saveMessage(String fromUser,String toUser,String message){
            //由于该消息是有用户输入的因此需要使用预编译
            try (
                    Connection connection=DBUtil.getConnection();
                    ){
                String sql="INSERT INTO chatinfo (from_user,to_user,content) VALUES(?,?,?)";
                PreparedStatement ps=connection.prepareStatement(sql);
                ps.setString(1,fromUser);
                ps.setString(2,toUser);
                ps.setString(3,message);
                int num=ps.executeUpdate();
                if (num>0){
                    System.out.println("保存成功");
                }else {
                    System.out.println("保存失败");
                }


            }catch (Exception e){
                e.printStackTrace();
            }




        }

    }




}
